package com.usian.search.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.util.JsonUtils;
import com.usian.model.search.dtos.UserSearchDto;
import com.usian.search.entity.ApAssociateWords;
import com.usian.search.mapper.ApAssociateWordsMapper;
import com.usian.search.model.Trie;
import com.usian.search.service.IApAssociateWordsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 联想词表 服务实现类
 * </p>
 *
 * @author usian
 * @since 2022-10-19
 */
@Service
public class ApAssociateWordsServiceImpl extends ServiceImpl<ApAssociateWordsMapper, ApAssociateWords> implements IApAssociateWordsService {

    @Override
    public List<ApAssociateWords> search(UserSearchDto dto) {
        //根据用户输入的关键字，进行模糊匹配查询
        QueryWrapper<ApAssociateWords> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(ApAssociateWords::getAssociateWords,dto.getSearchWords());
        List<ApAssociateWords> list = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"联想词不存在");
        }
        return list;
    }

    @Autowired
    private StringRedisTemplate redisTemplate;

    String PRE_FIX = "ld:search:associate:";

    @Override
    public List<ApAssociateWords> searchV2(UserSearchDto dto) {
        //1、尝试从redis中获取联想词列表
        String key=PRE_FIX+"list";
        String associateListStr = redisTemplate.opsForValue().get(key);
        List<ApAssociateWords> list = null;
        if(StringUtils.isEmpty(associateListStr)){
            //Redis中并没有存入联想词，查询数据库，并缓存到Redis中
            list = this.list();
            redisTemplate.opsForValue().set(key, JsonUtils.toString(list));
        }else{
            //Redis中已经存在联想词
            list = JsonUtils.toList(associateListStr,ApAssociateWords.class);
        }

        //2、构建tire树
        Trie trie = new Trie();
        for (ApAssociateWords apAssociateWords : list) {
            trie.insert(apAssociateWords.getAssociateWords());
        }
        //3、查询搜索关键字相关的联想词列表
        List<String> list1 = trie.startWith(dto.getSearchWords());
        //封装联想词对象集合
        List<ApAssociateWords> associateWordsList = new ArrayList<>();
        for (String str : list1) {
            ApAssociateWords apAssociateWords = new ApAssociateWords();
            apAssociateWords.setAssociateWords(str);
            associateWordsList.add(apAssociateWords);
        }
        return associateWordsList;
    }
}
